2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../jucer_Headers.h"
27 #include "jucer_ButtonDocument.h"
29 //==============================================================================
30 static const int normalOff
= 0;
31 static const int overOff
= 1;
32 static const int downOff
= 2;
33 static const int normalOn
= 3;
34 static const int overOn
= 4;
35 static const int downOn
= 5;
36 static const int background
= 6;
39 //==============================================================================
40 ButtonDocument::ButtonDocument()
42 paintStatesEnabled
[normalOff
] = true;
43 paintStatesEnabled
[overOff
] = true;
44 paintStatesEnabled
[downOff
] = true;
45 paintStatesEnabled
[normalOn
] = false;
46 paintStatesEnabled
[overOn
] = false;
47 paintStatesEnabled
[downOn
] = false;
48 paintStatesEnabled
[background
] = false;
50 parentClasses
= "public Button";
52 for (int i
= 7; --i
>= 0;)
54 paintRoutines
[i
] = new PaintRoutine();
55 paintRoutines
[i
]->setDocument (this);
56 paintRoutines
[i
]->setBackgroundColour (Colours::transparentBlack
);
60 ButtonDocument::~ButtonDocument()
62 for (int i
= 7; --i
>= 0;)
63 delete paintRoutines
[i
];
66 static const char* const stateNames
[] =
68 "normal", "over", "down",
69 "normal on", "over on", "down on",
73 int stateNameToIndex (const String
& name
)
75 for (int i
= 7; --i
>= 0;)
76 if (name
.equalsIgnoreCase (stateNames
[i
]))
84 int ButtonDocument::getNumPaintRoutines() const
88 for (int i
= 7; --i
>= 0;)
89 if (paintStatesEnabled
[i
])
95 const StringArray
ButtonDocument::getPaintRoutineNames() const
99 for (int i
= 0; i
< 7; ++i
)
100 if (paintStatesEnabled
[i
])
101 s
.add (stateNames
[i
]);
106 PaintRoutine
* ButtonDocument::getPaintRoutine (const int index
) const
110 for (int i
= 0; i
< 7; ++i
)
112 if (paintStatesEnabled
[i
])
115 return paintRoutines
[i
];
125 void ButtonDocument::setStatePaintRoutineEnabled (const int index
, bool b
)
127 jassert (index
> 0 && index
< 7);
129 if (paintStatesEnabled
[index
] != b
)
131 paintStatesEnabled
[index
] = b
;
136 bool ButtonDocument::isStatePaintRoutineEnabled (const int index
) const
138 return paintStatesEnabled
[index
];
141 int ButtonDocument::chooseBestEnabledPaintRoutine (int paintRoutineWanted
) const
143 switch (paintRoutineWanted
)
149 return paintStatesEnabled
[overOff
] ? overOff
: normalOff
;
152 return paintStatesEnabled
[downOff
] ? downOff
: chooseBestEnabledPaintRoutine (overOff
);
155 return paintStatesEnabled
[normalOn
] ? normalOn
: normalOff
;
158 return paintStatesEnabled
[overOn
] ? overOn
: (paintStatesEnabled
[normalOn
] ? normalOn
: chooseBestEnabledPaintRoutine (overOff
));
161 return paintStatesEnabled
[downOn
] ? downOn
162 : ((paintStatesEnabled
[overOn
] || paintStatesEnabled
[normalOn
])
163 ? chooseBestEnabledPaintRoutine (overOn
)
164 : chooseBestEnabledPaintRoutine (downOff
));
174 //==============================================================================
175 const String
ButtonDocument::getTypeName() const
180 JucerDocument
* ButtonDocument::createCopy()
182 ButtonDocument
* newOne
= new ButtonDocument();
184 newOne
->resources
= resources
;
185 newOne
->setFile (getFile());
187 XmlElement
* const xml
= createXml();
188 newOne
->loadFromXml (*xml
);
194 XmlElement
* ButtonDocument::createXml() const
196 XmlElement
* const doc
= JucerDocument::createXml();
198 for (int i
= 0; i
< 7; ++i
)
200 XmlElement
* e
= paintRoutines
[i
]->createXml();
201 e
->setAttribute ("buttonState", stateNames
[i
]);
202 e
->setAttribute ("enabled", paintStatesEnabled
[i
]);
204 doc
->addChildElement (e
);
210 bool ButtonDocument::loadFromXml (const XmlElement
& xml
)
212 if (JucerDocument::loadFromXml (xml
))
214 for (int i
= 7; --i
>= 0;)
215 paintStatesEnabled
[i
] = false;
217 forEachXmlChildElementWithTagName (xml
, e
, PaintRoutine::xmlTagName
)
219 const int stateIndex
= stateNameToIndex (e
->getStringAttribute ("buttonState"));
221 paintRoutines
[stateIndex
]->loadFromXml (*e
);
222 paintStatesEnabled
[stateIndex
] = e
->getBoolAttribute ("enabled", stateIndex
< normalOn
);
226 getUndoManager().clearUndoHistory();
233 void ButtonDocument::getOptionalMethods (StringArray
& baseClasses
,
234 StringArray
& returnValues
,
235 StringArray
& methods
,
236 StringArray
& initialContents
) const
238 JucerDocument::getOptionalMethods (baseClasses
, returnValues
, methods
, initialContents
);
240 addMethod ("Button", "void", "clicked()", "", baseClasses
, returnValues
, methods
, initialContents
);
241 addMethod ("Button", "void", "buttonStateChanged()", "", baseClasses
, returnValues
, methods
, initialContents
);
244 //==============================================================================
245 class ButtonStatePaintEnabledProperty
: public BooleanPropertyComponent
,
246 private ChangeListener
249 ButtonStatePaintEnabledProperty (const String
& name
, ButtonDocument
& document_
, const int stateMethod_
)
250 : BooleanPropertyComponent (name
, "enabled", "disabled"),
251 document (document_
),
252 stateMethod (stateMethod_
)
254 document
.addChangeListener (this);
257 ~ButtonStatePaintEnabledProperty()
259 document
.removeChangeListener (this);
262 void setState (bool newState
)
264 document
.setStatePaintRoutineEnabled (stateMethod
, newState
);
267 bool getState() const
269 return document
.isStatePaintRoutineEnabled (stateMethod
);
273 void changeListenerCallback (ChangeBroadcaster
*)
278 ButtonDocument
& document
;
279 const int stateMethod
;
282 void ButtonDocument::addExtraClassProperties (PropertyPanel
* panel
)
284 Array
<PropertyComponent
*> props
;
286 for (int i
= 1; i
< 7; ++i
)
287 props
.add (new ButtonStatePaintEnabledProperty (stateNames
[i
], *this, i
));
289 panel
->addSection ("Button paint routines", props
);
292 //==============================================================================
293 class ButtonTestComponent
: public Button
296 ButtonTestComponent (ButtonDocument
* const document_
, const bool alwaysFillBackground_
)
297 : Button (String::empty
),
298 document (document_
),
299 alwaysFillBackground (alwaysFillBackground_
)
301 setClickingTogglesState (true);
304 ~ButtonTestComponent()
308 void paintButton (Graphics
& g
, bool isMouseOverButton
, bool isButtonDown
)
310 if (document
->paintStatesEnabled
[background
])
312 document
->paintRoutines
[background
]->fillWithBackground (g
, alwaysFillBackground
);
313 document
->paintRoutines
[background
]->drawElements (g
, Rectangle
<int> (0, 0, getWidth(), getHeight()));
318 ? (isButtonDown
? document
->chooseBestEnabledPaintRoutine (downOn
)
319 : (isMouseOverButton
? document
->chooseBestEnabledPaintRoutine (overOn
)
320 : document
->chooseBestEnabledPaintRoutine (normalOn
)))
321 : (isButtonDown
? document
->chooseBestEnabledPaintRoutine (downOff
)
322 : (isMouseOverButton
? document
->chooseBestEnabledPaintRoutine (overOff
)
325 document
->paintRoutines
[stateIndex
]->fillWithBackground (g
, ! document
->paintStatesEnabled
[background
]);
326 document
->paintRoutines
[stateIndex
]->drawElements (g
, Rectangle
<int> (0, 0, getWidth(), getHeight()));
330 ButtonDocument
* const document
;
331 const bool alwaysFillBackground
;
334 Component
* ButtonDocument::createTestComponent (const bool alwaysFillBackground
)
336 return new ButtonTestComponent (this, alwaysFillBackground
);
339 //==============================================================================
340 void ButtonDocument::fillInGeneratedCode (GeneratedCode
& code
) const
342 JucerDocument::fillInGeneratedCode (code
);
344 code
.parentClassInitialiser
= "Button (" + quotedString (code
.componentName
) + ")";
345 code
.removeCallback ("void", "paint (Graphics& g)");
348 void ButtonDocument::fillInPaintCode (GeneratedCode
& code
) const
350 jassert (paintStatesEnabled
[normalOff
]);
351 String paintCode
[7];
353 for (int i
= 0; i
< 7; ++i
)
354 if (paintStatesEnabled
[i
])
355 paintRoutines
[i
]->fillInGeneratedCode (code
, paintCode
[i
]);
357 String
& s
= code
.getCallbackCode ("public Button",
359 "paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown)",
362 int numPaintRoutines
= getNumPaintRoutines();
364 if (paintStatesEnabled
[background
])
366 s
<< paintCode
[background
] << "\n";
370 if (numPaintRoutines
== 1)
372 s
<< paintCode
[normalOff
];
374 else if (numPaintRoutines
== downOff
&& (paintStatesEnabled
[overOff
] || paintStatesEnabled
[downOff
] || paintStatesEnabled
[normalOn
]))
376 if (paintStatesEnabled
[normalOn
])
378 s
<< "if (getToggleState())\n{\n "
379 << indentCode (paintCode
[normalOn
], 4).trimEnd();
381 else if (paintStatesEnabled
[overOff
])
383 s
<< "if (isButtonDown || isMouseOverButton)\n{\n "
384 << indentCode (paintCode
[overOff
], 4).trimEnd();
388 s
<< "if (isButtonDown)\n{\n "
389 << indentCode (paintCode
[downOff
], 4).trimEnd();
392 s
<< "\n}\nelse\n{\n "
393 << indentCode (paintCode
[normalOff
], 4).trimEnd()
396 else if (numPaintRoutines
== normalOn
&& paintStatesEnabled
[overOff
] && paintStatesEnabled
[downOff
])
398 s
<< "if (isButtonDown)\n{\n "
399 << indentCode (paintCode
[downOff
], 4).trimEnd()
400 << "\n}\nelse if (isMouseOverButton)\n{\n "
401 << indentCode (paintCode
[overOff
], 4).trimEnd()
403 << indentCode (paintCode
[normalOff
], 4).trimEnd()
408 if (paintStatesEnabled
[normalOn
] || paintStatesEnabled
[overOn
] || paintStatesEnabled
[downOn
])
410 s
<< "switch (getToggleState() ? (isButtonDown ? "
411 << chooseBestEnabledPaintRoutine (downOn
) << " : (isMouseOverButton ? "
412 << chooseBestEnabledPaintRoutine (overOn
) << " : "
413 << chooseBestEnabledPaintRoutine (normalOn
) << "))\n : (isButtonDown ? "
414 << chooseBestEnabledPaintRoutine (downOff
) << " : (isMouseOverButton ? "
415 << chooseBestEnabledPaintRoutine (overOff
) << " : 0)))\n{\n";
419 s
<< "switch (isButtonDown ? " << chooseBestEnabledPaintRoutine (downOff
)
420 << " : (isMouseOverButton ? " << chooseBestEnabledPaintRoutine (overOff
)
424 for (int i
= 0; i
< 6; ++i
)
426 if (paintStatesEnabled
[i
])
428 s
<< "case " << i
<< ":\n {\n "
429 << indentCode (paintCode
[i
], 8).trimEnd()
430 << "\n break;\n }\n\n";
434 s
<< "default:\n break;\n}\n";